using System;
using Impact.Model.Service;
using StructureMap;
using Impact.Model.Objects;
using System.Web;
using System.IO;
using System.Drawing;
using Impact.Infrastructure;
using System.Collections.Generic;

namespace Impact.Controllers
{
    /// <summary>
    /// Controller for photo galleries and photos
    /// </summary>
    public class PhotoController
    {
        private static readonly int ThumbnailMax = 118;

        /// <summary>
        /// get the relative path for photos for a given gallery
        /// </summary>
        public static string GetGalleryPath( PhotoGallery gallery )
        {
            string name = Utility.StripNonAlphaNumeric( gallery.Name );
            return string.Format( "~/images/gallery/{0}", name );
        }

        /// <summary>
        /// get the relative path for photos for a given photo
        /// </summary>
        public static string GetGalleryPath( Photo photo )
        {
            return Path.Combine( GetGalleryPath( photo.PhotoGallery ), photo.Filename );
        }

        /// <summary>
        /// get the relative path for thumbnails for a given gallery
        /// </summary>
        public static string GetThumbnailPath( PhotoGallery gallery )
        {
            string name = Utility.StripNonAlphaNumeric( gallery.Name );
            return string.Format( "~/images/gallery/{0}/thumbs", name );
        }

        /// <summary>
        /// get the relative path for thumbnails for a given photo
        /// </summary>
        public static string GetThumbnailPath( Photo photo )
        {
            return Path.Combine( GetThumbnailPath( photo.PhotoGallery ), photo.Filename );
        }


        /// <summary>
        /// Retieve all publicly visible galleries
        /// </summary>
        public static PhotoGalleryCollection GetVisibleGalleries()
        {
            IPhotoService service = ObjectFactory.GetInstance<IPhotoService>();
            return service.GetAllGalleries( true );
        }

        /// <summary>
        /// Retieve all galleries
        /// </summary>
        public static PhotoGalleryCollection GetAllGalleries()
        {
            IPhotoService service = ObjectFactory.GetInstance<IPhotoService>();
            return service.GetAllGalleries( false );
        }

        /// <summary>
        /// Delete the given gallery
        /// </summary>
        public static void DeleteGallery( string id )
        {
            IPhotoService service = ObjectFactory.GetInstance<IPhotoService>();
            service.DeleteGallery( id );
        }

        /// <summary>
        /// Add a gallery w/ the given name
        /// </summary>
        public static void AddGallery( string name )
        {
            IPhotoService service = ObjectFactory.GetInstance<IPhotoService>();
            PhotoGallery gallery = new PhotoGallery();
            gallery.Name = name;
            service.SaveGallery( gallery );
        }

        /// <summary>
        /// Retrieve a gallery based on the ID
        /// </summary>
        public static PhotoGallery GetGallery( string id )
        {
            IPhotoService service = ObjectFactory.GetInstance<IPhotoService>();
            return service.GetGallery( id );
        }

        /// <summary>
        /// This method syncs up the database w/ the filesystem for the given gallery
        /// </summary>
        public static void UpdateGallery( string galleryId )
        {
            IPhotoService service = ObjectFactory.GetInstance<IPhotoService>();
            PhotoGallery gallery = service.GetGallery( galleryId );
            DirectoryInfo galleryPath = new DirectoryInfo(
                HttpContext.Current.Server.MapPath( GetGalleryPath( gallery ) ) );
            string thumbnailPath = HttpContext.Current.Server.MapPath( GetThumbnailPath( gallery ) );
            if ( !galleryPath.Exists )
            {
                galleryPath.Create();
            }
            if ( !Directory.Exists( thumbnailPath ) )
            {
                Directory.CreateDirectory( thumbnailPath );
            }

            List<Photo> photoList = new List<Photo>( gallery.Photos );

            foreach ( FileInfo file in galleryPath.GetFiles() )
            {
                Photo record = null;
                int i = gallery.Photos.Find( Photo.Columns.Filename, file.Name );

                if ( i <= 0 )
                {
                    record = new Photo();
                    record.Filename = file.Name;
                    record.GalleryID = gallery.GalleryID;
                    record.Timestamp = System.Data.SqlTypes.SqlDateTime.MinValue.Value;

                    service.SavePhoto( record );
                }
                else
                {
                    record = gallery.Photos[i];

                    // the file was found on disk, so remove it from the list of files
                    // that need to be removed from the db
                    photoList.Remove( record );
                }

                // check if we need to update the thumbnail
                if ( !record.Timestamp.Equals( file.LastWriteTime ) )
                {
                    using ( Bitmap image = new Bitmap( file.FullName ) )
                    {
                        float aspectRatio = (float)image.Width / (float)image.Height;
                        int width, height;
                        if ( aspectRatio >= 1.0 )
                        {
                            width = ThumbnailMax;
                            height = (int)( ThumbnailMax / aspectRatio );
                        }
                        else
                        {
                            height = ThumbnailMax;
                            width = (int)( ThumbnailMax * aspectRatio );
                        }

                        using ( Image thumb = image.GetThumbnailImage( width, height, null, System.IntPtr.Zero ) )
                        {
                            thumb.Save( Path.Combine( thumbnailPath, file.Name ) );
                            record.Timestamp = file.LastWriteTime;
                            service.SavePhoto( record );
                        }
                    }
                }

            }

            // any remaining in photo list have been removed from the folder, so now
            // they need to be removed from the db
            foreach ( Photo photo in photoList )
            {
                service.DeletePhoto( photo.PhotoID.ToString() );
            }

        }

        /// <summary>
        /// Retrieve a photo based on the ID
        /// </summary>
        public static Photo GetPhoto( string id )
        {
            IPhotoService service = ObjectFactory.GetInstance<IPhotoService>();
            return service.GetPhoto( id );
        }

        /// <summary>
        /// Save the given photo
        /// </summary>
        public static void SavePhoto( Photo photo )
        {
            IPhotoService service = ObjectFactory.GetInstance<IPhotoService>();
            service.SavePhoto( photo );
        }

        /// <summary>
        /// Delete the given photo
        /// </summary>
        public static void DeletePhoto( string id )
        {
            IPhotoService service = ObjectFactory.GetInstance<IPhotoService>();
            Photo photo = service.GetPhoto( id );

            File.Delete( HttpContext.Current.Server.MapPath( Path.Combine( GetGalleryPath( photo.PhotoGallery ), photo.Filename ) ) );
            File.Delete( HttpContext.Current.Server.MapPath( Path.Combine( GetThumbnailPath( photo.PhotoGallery ), photo.Filename ) ) );

        }

        /// <summary>
        /// toggles the "visible" flag on the given gallery ID
        /// </summary>
        public static void ToggleVisible( string galleryId )
        {
            IPhotoService service = ObjectFactory.GetInstance<IPhotoService>();
            PhotoGallery gallery = service.GetGallery( galleryId );
            gallery.Visible = !gallery.Visible;
            service.SaveGallery( gallery );
        }
    }
}
